package com.inspur.edp.web.npmpackage.core.npminstall.global;

import com.inspur.edp.web.common.entity.CommandExecutedResult;
import com.inspur.edp.web.common.environment.ExecuteEnvironment;
import com.inspur.edp.web.common.environment.checker.ExecuteEnvironmentCheckResult;
import com.inspur.edp.web.common.environment.checker.ExecuteEnvironmentChecker;
import com.inspur.edp.web.common.io.FileUtility;
import com.inspur.edp.web.common.logger.WebLogger;
import com.inspur.edp.web.common.utility.CommandLineUtility;
import com.inspur.edp.web.common.utility.ResourceLocalizeUtil;
import com.inspur.edp.web.npmpackage.api.constant.I18nMsgConstant;
import com.inspur.edp.web.npmpackage.api.entity.NpmInstallParameter;
import com.inspur.edp.web.npmpackage.api.entity.NpmPackageResponse;
import com.inspur.edp.web.npmpackage.api.entity.packagejson.NpmPackageJsonDependencyInfo;
import com.inspur.edp.web.npmpackage.api.entity.packagejson.NpmPackageJsonInfo;
import com.inspur.edp.web.npmpackage.api.entity.settings.NpmUpdatePolicy;
import com.inspur.edp.web.npmpackage.core.npmpackagecheck.NpmPackageCheck;
import lombok.Data;

import java.util.Arrays;
import java.util.List;

/**
 * 是否安装全局包检测
 *
 * @author noah
 * 2023/9/22 09:32
 */
public class NpmInstallGlobalChecker {

    public static NpmInstallGlobalCheckResult check(boolean isUpgradeTool) {
        NpmInstallParameter npmInstallParameter = NpmInstallGlobalManager.getCurrentNpmInstallParameter(isUpgradeTool);
        return check(npmInstallParameter);
    }

    /**
     * 全局包版本检测
     *
     * @param npmInstallParameter
     * @return
     */
    public static NpmInstallGlobalCheckResult check(NpmInstallParameter npmInstallParameter) {
        NpmInstallGlobalCheckResult checkResult = NpmInstallGlobalCheckResult.init();
        if (npmInstallParameter.isOfflineMode()) {
            String errorMessage = ResourceLocalizeUtil.getString(I18nMsgConstant.WEB_NPM_PACKAGE_MSG_0029);
            return checkResult.setReason(errorMessage);
        }
        if (npmInstallParameter.getUpdatePolicy().equals(NpmUpdatePolicy.manual)) {
            String errorMessage = ResourceLocalizeUtil.getString(I18nMsgConstant.WEB_NPM_PACKAGE_MSG_0030);
            return checkResult.setReason(errorMessage);
        }
        if (npmInstallParameter.getUpdatePolicy().equals(NpmUpdatePolicy.never)) {
            String errorMessage = ResourceLocalizeUtil.getString(I18nMsgConstant.WEB_NPM_PACKAGE_MSG_0031);
            return checkResult.setReason(errorMessage);
        }

        String serverPackageJsonPath = GlobalPackageJsonPathGenerator.generate();
        // 获取package.json 文件路径
        String tmpPackageJsonFilePath = GlobalPackageJsonPathGenerator.getPackageJsonFilePathInTmpDir();
        // 主要是用来比较两个package.json 文件是否相同
        // 此处提取至NpmInstallGlobalManager的判断，但没有全部合并，主要是因为存在部分中间验证
        // 此处只是判断是否版本不一致
        if (FileUtility.exists(serverPackageJsonPath)) {
            if (!FileUtility.exists(tmpPackageJsonFilePath)) {
                // 如果临时目录的版本文件不存在 那么直接认为需要安装
                return checkResult.setNeedInstallParameter();
            }
            // 下面认为临时目录下的版本文件存在 那么进行版本比较，判定是否发生变更
            try {
                String serverPackageJsonContent = FileUtility.readAsString(serverPackageJsonPath);
                NpmPackageJsonInfo serverPackageJsonInfo = NpmPackageCheck.packageJsonInfoGenerate(serverPackageJsonContent);
                String tmpPackageJsonContent = FileUtility.readAsString(tmpPackageJsonFilePath);
                NpmPackageJsonInfo tmpPackageJsonInfo = NpmPackageCheck.packageJsonInfoGenerate(tmpPackageJsonContent);

                // 查看全局命令版本是否正确，不正常必须执行全局安装
                CommandExecutedResult globalJit = CommandLineUtility.runCommandWithoutThrows("jit --version");
                if (globalJit.getExitCode() == 0) {
                    List<NpmPackageJsonDependencyInfo> dependencies = serverPackageJsonInfo.getDependencies();
                    // 取@farris/jie-engine版本号
                    NpmPackageJsonDependencyInfo farrisJieEngine = dependencies.stream().filter(dependency -> dependency.getKey().equals("@farris/jit-engine")).findFirst().orElse(null);
                    if (farrisJieEngine != null) {
                        String jitVersion = globalJit.getOutputInfo();
                        if (!jitVersion.equals(farrisJieEngine.getValue())) {
                            return checkResult.setNeedInstallParameter();
                        }
                    }
                } else {
                    return checkResult.setNeedInstallParameter();
                }

                // 设置其是否必须install选项
                checkResult.setNeedInstall(!serverPackageJsonInfo.equals(tmpPackageJsonInfo));
                return checkResult;
            } catch (Exception ex) {
                // 此处捕获异常的目的是为了避免读取字符串出现错误
                // 此处的错误不应当影响后续执行
                WebLogger.Instance.info("Npm版本比较" + ex.getMessage() + Arrays.toString(ex.getStackTrace()), NpmInstallGlobalChecker.class.getName());
                return checkResult.setNeedInstallParameter();
            }
        }


        return checkResult.setNeedInstallParameter();
    }

    /**
     * npm 全局包安装检测是否应当安装
     */
    @Data
    public static class NpmInstallGlobalCheckResult {
        /**
         * 是否允许安装标识
         */
        private boolean needInstall = false;

        /**
         * 无法安装原因
         */
        private String reason;

        public NpmInstallGlobalCheckResult setNeedInstallParameter() {
            this.setNeedInstall(true);
            return this;
        }

        public NpmInstallGlobalCheckResult setReason(String reason) {
            this.reason = reason;
            this.setNeedInstall(false);
            return this;
        }

        /**
         * 初始化
         *
         * @return
         */
        public static NpmInstallGlobalCheckResult init() {
            return new NpmInstallGlobalCheckResult();
        }
    }
}
